package com.xiao.pool;

import lombok.Data;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;

/**
 * @author Xiao
 * @version 1.0
 * @description 动态代理实现对数据库的连接
 * @date 2022/1/2 21:13
 */
@Data
public class ConnectionProxy implements InvocationHandler {
    //真实连接
    private Connection realConnection;
    //代理连接
    private Connection proxyConnection;
    //数据源
    private MyDataSource myDataSource;

    /**
     * 构造方法，初始化数据
     * @param realConnection
     * @param myDataSource
     */
    public ConnectionProxy(Connection realConnection, MyDataSource myDataSource) {
        //初始化真实连接和数据源
        this.realConnection = realConnection;
        this.myDataSource = myDataSource;
        //初始化代理连接 --> Proxy.newProxyInstance()
        this.proxyConnection = (Connection) Proxy.newProxyInstance(
                Connection.class.getClassLoader(),
                new Class[]{Connection.class},
                this);
    }

    /**
     * 通过动态代理获取连接对象，当用户调用Connection的方法时会走此方法
     * invoke()可以对请求做拦截处理，方便对连接做管理：如拦截close()方法，将连接放入连接池中，而不是直接销毁
     * @param proxy
     * @param method
     * @param args
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //获取方法名
        String methodName = method.getName();
        //如果方法是close()方法，把连接归还到连接池
        if ("close".equals(methodName)) {
            //TODO 把连接归还到连接池逻辑
            myDataSource.closeConnection(this);
            return null;
        } else {
            //其他方法直接调用真实连接对象执行
            return method.invoke(realConnection, args);
        }
    }
}
